package com.tdcoding.chat.manager;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.tdcoding.chat.action.common.ActionContext;
import com.tdcoding.chat.action.common.ActionRunnable;
import com.tdcoding.chat.configure.Configuration;
import com.tdcoding.chat.constants.MainConstants;
import com.tdcoding.chat.entities.ChannelInfo;
import com.tdcoding.chat.entities.FriendInfo;
import com.tdcoding.chat.entities.MemberInfo;
import com.tdcoding.chat.entities.RequestInfo;
import com.tdcoding.chat.helper.Logger;
import com.tdcoding.chat.server.ChatServer;

import io.netty.channel.Channel;

public class ChatManager implements RejectedExecutionHandler {
	private static final String TAG = "TDCChatManager";
	
	private static ChatManager chatManager;
	private static ConcurrentHashMap<Long, ChannelInfo> mChannelInfoMap;

	private static ExecutorService executorService;
	
	private ChatServer chatServer;

	public static ChatManager getInstance() {
		if (chatManager == null) {
			chatManager = new ChatManager();
		}
		return chatManager;
	}

	private ChatManager() {
		Configuration.getInstance();// 初始配置文件
		mChannelInfoMap = new ConcurrentHashMap<Long, ChannelInfo>();
		executorService = new ThreadPoolExecutor(MainConstants.CORE_POOL_SIZE, 
				MainConstants.MAX_POOL_SIZE,0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),
				this);
//		chatServer = new ChatServer();
	}

	public void executeRunnable(ActionRunnable runnable){
		executorService.execute(runnable);
	}
	
	/**
	 * 保存channel
	 * 
	 * @param channel
	 * @param channelInfo
	 *            1核心业务；2聊天；3文件
	 * @return
	 */
	public static ChannelInfo addChannelInfo(Channel channel,
			ChannelInfo channelInfo) {
		channelInfo.setChatChannel(channel);
		return mChannelInfoMap.put(channelInfo.getUserId(), channelInfo);
	}

	/**
	 * 更新ChannelInfo
	 * 
	 * @param userId
	 * @param channel
	 * @param channelType
	 *            1核心业务；2聊天；3文件
	 * @return
	 */
	public static ChannelInfo updateChannelInfo(long userId, int channelType,
			Channel channel) {
		ChannelInfo channelInfo = getChannelInfo(userId);
		if (channelInfo != null) {
			if (channel != null) {
				switch (channelType) {
				case MainConstants.CHANNEL_TYPE_CHAT:
					channelInfo.setChatChannel(channel);
					break;
				case MainConstants.CHANNEL_TYPE_FILE:
					channelInfo.setFileChannel(channel);
					break;
				}
			}
			return mChannelInfoMap.put(userId, channelInfo);
		}
		return null;
	}

	/**
	 * 移除session
	 * 
	 * @param userId
	 * @param channelId
	 *            0注销；1核心业务；2聊天；3文件
	 * @return
	 */
	public static boolean removeChannelInfo(int channelType, long userId) {
		ChannelInfo channelInfo = getChannelInfo(userId);
		boolean removed = false;
		if (channelInfo != null) {
			removed = mChannelInfoMap.remove(userId, channelInfo);
			if (removed) {
				channelInfo.realseChannel(MainConstants.CHANNEL_TYPE_ALL);
			}
		}
		return removed;
	}

	public static long getChannelInfo(Channel channel) {
		for (ChannelInfo channelInfo : mChannelInfoMap.values()) {
			if (channelInfo.getChatChannel() != null
					&& channelInfo.getChatChannel().equals(channel)) {
				return channelInfo.getUserId();
			}
		}
		return 0;
	}

	/**
	 * 根据userId获取
	 * 
	 * @param userId
	 * @return
	 */
	public static ChannelInfo getChannelInfo(long userId) {
		Logger.println(TAG, "getChannelInfo", userId);
		ChannelInfo channelInfo = mChannelInfoMap.get(userId);
		return channelInfo;
	}

	/**
	 * 更新channel
	 * 
	 * @param channel
	 * @param status
	 * @return
	 */
	public static void updateChannelInfo(Channel channel, int status) {
		for (ChannelInfo channelInfo : mChannelInfoMap.values()) {
			if (channelInfo.getChatChannel() != null
					&& channelInfo.getChatChannel().equals(channel)) {
				if (channelInfo.getChatChannel() != null
						&& channelInfo.getChatChannel().equals(channel)) {
					channelInfo.setStatus(status);
					mChannelInfoMap.put(channelInfo.getUserId(), channelInfo);
					break;
				}
			}
		}
	}

	/**
	 * 更新在线状态
	 * 
	 * @param userId
	 * @param status
	 * @return
	 */
	public static ChannelInfo updateChannelInfo(long userId, int status) {
		ChannelInfo channelInfo = getChannelInfo(userId);
		if (channelInfo != null) {
			channelInfo.setStatus(status);
			return mChannelInfoMap.put(userId, channelInfo);
		}
		return null;
	}

	/**
	 * 是否存在
	 * 
	 * @param userId
	 */
	public static boolean existChannelInfo(long userId) {
		ChannelInfo channelInfo = getChannelInfo(userId);
		return channelInfo == null ? false : true;
	}

	/**
	 * 根据多个群成员ID获取ChannelInfo
	 * 
	 * @param lMemberInfos
	 * @return
	 */
	public static List<ChannelInfo> getMemberChannelInfos(
			List<MemberInfo> lMemberInfos) {
		ArrayList<ChannelInfo> lChannelInfos = new ArrayList<ChannelInfo>();
		for (MemberInfo memberInfo : lMemberInfos) {
			ChannelInfo channelInfo = getChannelInfo(memberInfo.getMemberId());
			if (channelInfo == null) {
				channelInfo = new ChannelInfo();
				channelInfo.setUserId(memberInfo.getMemberId());
				channelInfo.setNickName(memberInfo.getNickName());
				channelInfo.setUserName(memberInfo.getMemberName());
				channelInfo.setStatus(MainConstants.USER_STATUS_OFFLINE);
			}
			lChannelInfos.add(channelInfo);
		}
		return lChannelInfos;
	}

	/**
	 * 根据多个用户ID获取ChannelInfo
	 * 
	 * @param lUserInfos
	 * @return
	 */
	public static ArrayList<Serializable> getUserChannelInfos(
			ArrayList<FriendInfo> lFriendInfos) {
		ArrayList<Serializable> lChannelInfos = new ArrayList<Serializable>();
		for (FriendInfo friendInfo : lFriendInfos) {
			ChannelInfo channelInfo = getChannelInfo(friendInfo.getFriendId());
			if (channelInfo == null) {
				channelInfo = new ChannelInfo();
				channelInfo.setUserId(friendInfo.getFriendId());
				channelInfo.setNickName(friendInfo.getFriendName());
				channelInfo.setStatus(MainConstants.USER_STATUS_OFFLINE);
			}
			lChannelInfos.add(channelInfo);
		}
		return lChannelInfos;
	}

	/**
	 * 获取系统所有ChannelInfo
	 * 
	 * @return
	 */
	public static ArrayList<ChannelInfo> getAllChannelInfos() {
		ArrayList<ChannelInfo> lChannelInfos = new ArrayList<ChannelInfo>();
		for (ChannelInfo channelInfo : mChannelInfoMap.values()) {
			if (channelInfo != null) {
				lChannelInfos.add(channelInfo);
			}
		}
		return lChannelInfos;
	}

	@Override
	public void rejectedExecution(Runnable runnable,
			ThreadPoolExecutor threadPoolExecutor) {
		Logger.println(this, "rejectedExecution", runnable);
		ActionRunnable actionRunnable = (ActionRunnable) runnable;
		RequestInfo requestInfo=actionRunnable.getRequestInfo();
		ActionContext.writeResponse(actionRunnable.getChannel(),requestInfo.getPacketId(),requestInfo.getMethod(),-1,"Server busying, please try again later.");
	}
	
	/**
	 * 关闭所有服务
	 */
	public void shutdownServer() {
		mChannelInfoMap.clear();
		chatServer.shutdownServer();
	}
	
	public static void main(String[] args) throws Exception {
		ChatManager.getInstance();
		// String
		// columns="userId,userName,identity,lplatform,rplatform,plainPwd,encryptedPwd,allowedAdd,creationDate";
		// String
		// values="11423035840241,'13612935692',0,-1,0,'e10adc3949ba59abbe56e057f20f883e','14e1b600b1fd579f47433b88e8d85291',0,'1423035840243'";
		// int result=DBManager.insertSql("tdcoding", "ofUser", columns,
		// values);
		// System.out.println(result);
//		String pwd=SecurityHelper.encryptMD5("111111");
//		pwd=SecurityHelper.encryptSHA(pwd);
//		System.out.println(pwd);
//		RequestInfo requestInfo =new RequestInfo();
//		UserInfo userInfo = new UserInfo();
//		userInfo.setUserName("13612935691");
//		userInfo.setNickName("sasa");
//		userInfo.setSex("男");
//		userInfo.setPassword(SecurityHelper.encryptMD5("111111"));
//		requestInfo.setParameters(new Object[] {userInfo});
//		CoreAction coreAction=new CoreAction();
//		coreAction.register(null, requestInfo);
//		Logger.println("main", "coreAction", coreAction);
		
	}
}
